package com.agileboot.domain.app.product.utils;

import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;

import lombok.Data;
import org.springframework.stereotype.Component;

/**
 * 我想做一个个人信贷系统，现在需要一个工具类,目前我设计了三个版块，分别是：个人基础信息、个人房产信息、个人汽车信息，这三个模块是独立存在的，我期望的用户每填写一个模块，就自动生成一个贷款申请单，并且这个贷款申请单可以保存到数据库中，然后用户可以查看自己所有的贷款申请，管理员如果审核通过了这笔贷款申请，那么就给用户账号加贷款额度，并且用户可以查看自己的账户余额。请帮我实现这个工具类。类中我使用了 import lombok.Data;和
 * import org.springframework.stereotype.Component; 注解
 */

@Component
@Data
public class LoanCalculator {
    // #用户信息
    // 姓名
    private String name;
    // 年龄
    private int age;
    // 月收入
    private double monthlyIncome;
    // 职业
    private String occupation;
    // 信用记录分数
    private int creditScore;
    // 总负债(人民币:元)
    private double totalLiabilities;

    // #产品信息
    // 贷款类型
    private String loanType;
    // 贷款期限
    private int loanTerm;
    // 利率
    private double interestRate;
    // 还款方式
    private String repaymentMethod;
    // 产品最长贷款期限（月）
    private int maxLoanTerm;
    // 产品最大贷款金额
    private double maxLoanAmount;


    // 常量定义
    private static final double MIN_LOAN_AMOUNT = 1000.0; // 最小贷款额度
    private static final int MIN_CREDIT_SCORE = 300; // 最低信用分数
    private static final int MAX_CREDIT_SCORE = 850; // 最高信用分数
    private static final double MAX_ADJUSTMENT_FACTOR = 1.5; // 最大调整因子

    /**
     * 检查贷款申请是否合格方法
     *
     * @param requestedLoanAmount 请求的贷款金额
     * @param maxAffordableAmount
     * @return 如果贷款申请合格则返回 true，否则返回 false
     */
    public boolean checkLoanEligibility(double requestedLoanAmount, double maxAffordableAmount) {
        // 假设简单地检查贷款额度是否超过最大可承受额度
        // 如果请求的贷款金额小于等于最大可承受额度，则认为贷款申请合格
        return requestedLoanAmount <= maxAffordableAmount;
    }


    /**
     * 计算贷款额度方法
     *
     * @return 返回计算出的贷款额度
     */
    public double calculateLoanAmount() {
        // 假设贷款额度由以下因素决定：
        // 1. 月收入的某个比例（例如80%）
        // 2. 信用分数调整因子（信用分数越高，调整因子越大）
        // 3. 总负债的影响（从月收入中减去总负债的一定比例，例如50%）


        // 1. 计算基于月收入的贷款额度基础值
        double baseLoanAmount = monthlyIncome * 0.8;

        // 2. 根据信用分数调整贷款额度
        // 这里假设信用分数越高，贷款额度调整因子越大，但不超过一定上限
        double creditAdjustmentFactor = calculateCreditAdjustmentFactor(creditScore);
        baseLoanAmount *= creditAdjustmentFactor;

        // 3. 考虑总负债对贷款额度的影响
        // 从贷款额度基础值中减去总负债的一定比例
        baseLoanAmount -= totalLiabilities * 0.5;

        // 确保贷款额度不低于某个最小值
        baseLoanAmount = Math.max(baseLoanAmount, MIN_LOAN_AMOUNT);

        // 返回最终的贷款额度
        return baseLoanAmount;
    }

    /**
     * 根据信用分数计算贷款额度调整因子
     *
     * @param creditScore 信用分数
     * @return 贷款额度调整因子
     */
    private double calculateCreditAdjustmentFactor(int creditScore) {
        // 假设信用分数越高，调整因子越大，但不超过1.5
        // 这里使用一个简单的线性插值来模拟这个过程
        // 实际中，这个映射关系可能会更复杂，可能是一个非线性函数或基于某种统计模型的计算
        double adjustmentFactor = 1.0 + (creditScore - MIN_CREDIT_SCORE) / (MAX_CREDIT_SCORE - MIN_CREDIT_SCORE) * (MAX_ADJUSTMENT_FACTOR - 1.0);
        return Math.min(adjustmentFactor, MAX_ADJUSTMENT_FACTOR);
    }


    /**
     * 生成还款计划方法
     *
     * @param loanAmount 贷款金额
     * @param loanTerm   贷款期限（月）
     * @return 返回生成的还款计划列表
     */
    public List<String> generateRepaymentSchedule(double loanAmount, int loanTerm) {
        List<String> repaymentSchedule = new ArrayList<>();
        // 计算月利率
        double monthlyInterestRate = interestRate / 12;

        // 每月还款金额（利息 + 本金）
        double monthlyPayment = loanAmount * monthlyInterestRate / (1 - Math.pow(1 + monthlyInterestRate, -loanTerm));
        DecimalFormat df = new DecimalFormat("#.00");

        // 剩余贷款金额
        double remainingLoanAmount = loanAmount;

        // 生成还款计划
        for (int i = 1; i <= loanTerm; i++) {
            // 计算本月利息
            double interestPayment = remainingLoanAmount * monthlyInterestRate;
            // 本月应还款额
            double totalPayment = monthlyPayment;
            // 更新剩余贷款金额
            remainingLoanAmount -= (monthlyPayment - interestPayment);
            // 构建还款计划字符串
            String paymentInfo = "第 " + i + " 期：本月应还款额 " + df.format(totalPayment) + "（本金 " + df.format(monthlyPayment - interestPayment) + "，利息 " + df.format(interestPayment) + "）";
            repaymentSchedule.add(paymentInfo);
        }

        return repaymentSchedule;
    }


    // 主方法用于测试
    public static void main(String[] args) {
        // 创建 LoanCalculator 实例并设置用户信息和产品信息
        LoanCalculator loanCalculator = new LoanCalculator();
        loanCalculator.setName("张三");
        loanCalculator.setAge(35);
        loanCalculator.setMonthlyIncome(50000);
        loanCalculator.setOccupation("工程师");
        loanCalculator.setCreditScore(750);
        loanCalculator.setTotalLiabilities(100);

        loanCalculator.setLoanType("个人贷款");
        loanCalculator.setLoanTerm(36);
        loanCalculator.setInterestRate(0.17);
        loanCalculator.setRepaymentMethod("等额本息");

        // 用户请求的贷款金额
        double requestedLoanAmount = 30000;


        // 计算最大可承受的贷款额度
        double maxAffordableAmount = loanCalculator.calculateLoanAmount();


        // 检查贷款申请是否合格
//        boolean isEligible = loanCalculator.checkLoanEligibility(requestedLoanAmount, maxAffordableAmount);
        boolean isEligible = true;

        if (isEligible) {
            System.out.println("恭喜！您的贷款申请已经通过。");
            System.out.println("贷款金额: $" + requestedLoanAmount);
            System.out.println("\n还款计划:");
            List<String> repaymentSchedule = loanCalculator.generateRepaymentSchedule(requestedLoanAmount, loanCalculator.getLoanTerm());
            for (String payment : repaymentSchedule) {
                System.out.println(payment);
            }
        } else {
            System.out.println("抱歉，您的贷款申请未通过。");
        }
    }
}

